﻿using System.Collections.Generic;
using System.Text;
using System.Web;
using SVTTranslateTextEngine.Core.Entries;

namespace SVTTranslateTextEngine.Core
{
    /// <summary>
    /// This class handles how to use the google translate api .
    /// </summary>
    public abstract class TranslatorByGoogle : TranslatorByHttp
    {
        protected string m_AppId;

        /// <summary>
        /// Enable one of the google app id in 
        /// </summary>
        protected TranslatorByGoogle()
        {
            m_AppId = ApiSetting.GetGoogleTranslateAppId();
        }

        /// <summary>
        /// Enable the GoogleAppId specified
        /// </summary>
        /// <param name="appIdIndex">Index of the Google App ID </param>
        protected TranslatorByGoogle(int appIdIndex)
        {
            m_AppId = ApiSetting.GetGoogleTranslateAppId(appIdIndex);
        }

        /// <summary>
        /// Translate the long sentence, it will break the snetence in the process
        /// </summary>
        /// <param name="longSentence">Long sentence (Source text ) </param>
        /// <param name="srcLangKey">Source language code </param>
        /// <param name="trgLangKey">Target language code </param>
        /// <param name="autoCheckLangKey">the source language code will auto checked in  the translation  process </param>
        /// <returns>the result is the target long sentence </returns>
        public string GetTranslationsByLongSentence(string longSentence, string srcLangKey, string trgLangKey,
                                                    ref string autoCheckLangKey)
        {
            var splitKeyVals = new List<string>();
            List<string> lstShotSentence = null;
                lstShotSentence = BreakSentenceHelper.SplitSentence(longSentence, ref splitKeyVals);
            string[] ss = GetTranslations(lstShotSentence, splitKeyVals, srcLangKey, trgLangKey, ref autoCheckLangKey);
            var sb = new StringBuilder();
            foreach (string str in ss)
                sb.Append(str);
            return HttpUtility.UrlDecode(sb.ToString());
        }

        /// <summary>
        /// Translate the long sentence, it will break the snetence in the process 
        /// </summary>
        /// <param name="longSentence">Long sentence (Source text ) </param>
        /// <param name="srcLangKey">Source language code </param>
        /// <param name="trgLangKey">Target language code </param>
        /// <returns>the result is the target long sentence </returns>
        public string GetTranslationsByLongSentence(string longSentence, string srcLangKey, string trgLangKey)
        {
            string autoCheckLangKey = null;
            return GetTranslationsByLongSentence(longSentence, srcLangKey, trgLangKey, ref autoCheckLangKey);
        }

        public abstract object GetTranslations(List<string> shotSentence, string srcLangKey, string trgLangKey);

        /// <summary>
        /// Translate multiple shot-sentences.
        /// </summary>
        /// <param name="shotSentence">the set of shot sentences </param>
        /// <param name="splitKeyVals">values of split point </param>
        /// <param name="szFromLang">source language code  </param>
        /// <param name="szToLang">target language code  </param>
        /// <param name="autoCheckLangKey">the source language code will auto checked in  the translation  process </param>
        /// <returns>the array of multiple shot-sentences </returns>
        public string[] GetTranslations(List<string> shotSentence, List<string> splitKeyVals, string szFromLang,
                                        string szToLang, ref string autoCheckLangKey)
        {
            var needToTranslate = new List<string>(); //The set saves the shot sentences which need to translated 
            var indexMapping = new int[shotSentence.Count]; //The record shotSentence every one phrase corresponding element in the needToTranslate capacity
            var reVal = new string[shotSentence.Count]; //Translate the results , consistent with the size of the array and order and shotSentence of
            for (int i = 0; i < shotSentence.Count; i++)
            {
                string transSrcVal = shotSentence[i];
                if (transSrcVal.Length > 0)
                {
                    int tempIndex = needToTranslate.IndexOf(transSrcVal);
                    if (tempIndex < 0)
                    {
                        if (transSrcVal.Trim().Length > 0)
                            needToTranslate.Add(transSrcVal); //Needs to Translate the phrase , and join the needToTranslate container
                        indexMapping[i] = needToTranslate.Count - 1;
                    }
                    else
                        indexMapping[i] = tempIndex;
                }
                else
                    indexMapping[i] = -1;
            }

            List<string> lstTrgSentences = GetTranslationsByEachTime(needToTranslate, 5, szFromLang, szToLang,
                                                                     ref autoCheckLangKey);

            if (lstTrgSentences.Count == needToTranslate.Count)
            {
                for (int i = 0; i < indexMapping.Length; i++)
                {
                    if (indexMapping[i] > -1)
                        reVal[i] = lstTrgSentences[indexMapping[i]];
                    if (splitKeyVals.Count > i)
                        reVal[i] = splitKeyVals[i] + reVal[i];
                }
            }

            return reVal;
        }

        /// <summary>
        /// Translate multiple shot-sentences , and do translaion in many times .
        /// </summary>
        /// <param name="shotSentence">the set of shot sentences </param>
        /// <param name="transAmountEachTime">how many shot sentence to translated each time </param>
        /// <param name="srcLangKey">source language code </param>
        /// <param name="trgLangKey">target language code </param>
        /// <param name="autoCheckSrcLangKey">the source language code will auto checked in  the translation  process</param>
        /// <returns>the array of multiple shot-sentences</returns>
        public List<string> GetTranslationsByEachTime(List<string> shotSentence, int transAmountEachTime,
                                                      string srcLangKey, string trgLangKey,
                                                      ref string autoCheckSrcLangKey)
        {
            var lstTrgSentences = new List<string>();
            var eachTranslateSources = new List<string>();
            int qValLen = 0;
            for (int i = 0; i < shotSentence.Count; i++)
            {
                string val = shotSentence[i];
                qValLen += val.Length;
                eachTranslateSources.Add(val);
                if ((i + 1)%transAmountEachTime == 0 || (i + 1) == shotSentence.Count)
                {
                    object obj = GetTranslations(eachTranslateSources, srcLangKey, trgLangKey);
                    if (obj != null)
                    {
                        if (obj is List<TranslationResult>)
                        {
                            foreach (var eachResult in ((List<TranslationResult>)obj))
                            {
                                foreach (var trans in eachResult.Data.Translations)
                                {
                                    lstTrgSentences.Add(trans.TranslatedText);
                                    if (string.IsNullOrEmpty(autoCheckSrcLangKey))
                                        autoCheckSrcLangKey = trans.DetectedSourceLanguage;
                                }
                            }
                        }
                    }
                    eachTranslateSources.Clear();
                }
            }
            return lstTrgSentences;
        }
    }
}